package main

import (
	"fmt"
	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"pids-cloud-server/app/router"
	"pids-cloud-server/config"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"pids-cloud-server/task"
	"pids-cloud-server/utils"
	"pids-cloud-server/version"
	"sync"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/robfig/cron/v3"
)

func main() {
	// 打印版本信息
	version.PrintVersion()
	// 在启动 Gin 服务器前，启动初始化任务
	var wg sync.WaitGroup
	wg.Add(1)
	go initialize(&wg)

	// 初始化 Gin 引擎
	engine := gin.Default()

	router.Routers(engine)
	wg.Add(1)
	go startCronTasks(&wg)
	wg.Wait()

	go start()
	// 启动 HTTP 服务
	go func() {
		if err := engine.Run(":9999"); err != nil {
			logging.Fatal(err.Error())
		}
	}()

	// 启动pprof端点
	go func() {
		log.Println(http.ListenAndServe("0.0.0.0:6060", nil))
	}()
	// 创建一个通道，用于接收停止信号
	stopChan := make(chan os.Signal, 1)
	signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
	// 主循环，检查停止信号
	for {
		select {
		case <-stopChan:
			return
		default:
			time.Sleep(100 * time.Millisecond)
		}
	}
}

var heartBeatcfg = config.HeartBeatCfg

func start() {
	// 主节点逻辑：定期发送心跳
	logging.Infof("[Leader]:%t", heartBeatcfg.Leader)
	if heartBeatcfg.Leader {
		//对端节点为空，说明是单节点服务
		if heartBeatcfg.PeerIP != "" {
			for {
				conn, err := net.Dial("tcp", heartBeatcfg.PeerIP+":"+heartBeatcfg.ListenPort)
				if err != nil {
					fmt.Println("[Leader] Error sending heartbeat:", err)
					time.Sleep(heartBeatcfg.HeartbeatInterval)
					continue
				}
				_, _ = conn.Write([]byte("heartbeat"))
				conn.Close()
				fmt.Println("[Leader] Heartbeat sent")
				time.Sleep(heartBeatcfg.HeartbeatInterval)
			}
		}
	} else {
		// 备节点逻辑：监听心跳，超时切换为主
		listener, err := net.Listen("tcp", ":"+heartBeatcfg.ListenPort)
		if err != nil {
			fmt.Println("[Backup] Error starting listener:", err)
			return
		}
		defer listener.Close()

		lastHeartbeat := time.Now()
		// 超时检测 Goroutine
		go func() {
			for {
				if time.Since(lastHeartbeat) > heartBeatcfg.TimeoutThreshold {
					fmt.Println("[Backup] No heartbeat received. Switching to Leader!")
					heartBeatcfg.Leader = true
				}
				time.Sleep(1 * time.Second)
			}
		}()

		// 监听心跳
		for {
			conn, err := listener.Accept()
			if err != nil {
				fmt.Println("[Backup] Connection error:", err)
				continue
			}
			lastHeartbeat = time.Now() // 更新心跳时间
			heartBeatcfg.Leader = false
			fmt.Println("[Backup] Heartbeat received")
			conn.Close()
		}
	}

}

// 采用cron定时任务实现
func startCronTasks(wg *sync.WaitGroup) {
	defer wg.Done()
	//创建一个默认的cron实例
	c := cron.New(cron.WithSeconds())
	//每30秒	执行一次
	c.AddFunc("0,30 * * * * *", func() {
		if heartBeatcfg.Leader {
			task.SnmpTask()
		}
	})
	//每60秒	执行一次
	c.AddFunc("0 */1 * * * *", func() {
		if heartBeatcfg.Leader {
			task.CommitTask()
		}
	})
	//每2分钟 执行一次
	c.AddFunc("0 */2 * * * *", func() {
		if heartBeatcfg.Leader {
			task.HostDownTask()
		}
	})
	//数据库采集每5分钟 执行一次
	c.AddFunc("0 */5 * * * *", func() {
		if heartBeatcfg.Leader {
			task.DbTask()
		}
	})
	//redis采集每5分钟 执行一次
	c.AddFunc("0 */5 * * * *", func() {
		if heartBeatcfg.Leader {
			task.RedisTask()
		}
	})
	//docker容器采集每5分钟 执行一次
	c.AddFunc("0 */5 * * * *", func() {
		if heartBeatcfg.Leader {
			task.DockerTask()
		}
	})
	//接口健康监测每一分钟执行一次
	c.AddFunc("30 */1 * * * *", func() {
		if heartBeatcfg.Leader {
			task.UrlHealthCheckTask()
		}
	})
	//每天凌晨1点10分执行一次
	c.AddFunc("0 10 1 * * ?", func() {
		if heartBeatcfg.Leader {
			task.ClearLogTask()
		}
	})
	c.Start()
}

func initialize(wg *sync.WaitGroup) {
	defer wg.Done()
	db := utils.GetDB()
	if db == nil {
		logging.Error("数据库连接失败，初始化失败")
		return
	}
	var modelOids []entity.ModelOid
	if tx := db.Find(&modelOids); tx.Error == nil && len(modelOids) > 0 {
		// 创建一个 map，用于根据 Model 字段分组
		modelGroupedOids := make(map[string][]entity.ModelOid)

		// 遍历查询结果，根据 Model 字段分组
		for _, modelOid := range modelOids {
			modelGroupedOids[modelOid.Model] = append(modelGroupedOids[modelOid.Model], modelOid)
		}
		var snmpOidList []entity.SnmpOid
		var results []SnmpIpCount

		// 查询每个 ip 对应的数量
		err := db.Model(&entity.SnmpInfo{}).
			Select("ip,m_snmp_info.model, COUNT(m_snmp_oid.oid_name) as count").
			Joins("left join m_snmp_oid on m_snmp_oid.snmp_ip = m_snmp_info.ip").
			Group("ip,m_snmp_info.model").
			Scan(&results).Error
		if err != nil {
			logging.Error("查询ip对应的数量失败", err)
		}
		for _, v := range results {
			if v.Count == 0 {
				snmpOids := generateSnmpOidList(modelGroupedOids, v)
				snmpOidList = append(snmpOidList, snmpOids...)
			}
		}
		if len(snmpOidList) > 0 {
			db.CreateInBatches(&snmpOidList, 1000)
		}
	}
}

func generateSnmpOidList(modelGroupedOids map[string][]entity.ModelOid, snmpIpCount SnmpIpCount) []entity.SnmpOid {
	modelOidList := modelGroupedOids[snmpIpCount.Model]
	var snmpOidList []entity.SnmpOid
	for _, modelOid := range modelOidList {
		snmpOidList = append(snmpOidList, entity.SnmpOid{
			Snmpip:   snmpIpCount.Ip,
			OidName:  modelOid.OidName,
			OidValue: modelOid.OidValue,
			Descr:    modelOid.Descr,
		})
	}
	return snmpOidList
}

type SnmpIpCount struct {
	Ip    string
	Model string
	Count int64
}
